/**
 * 所有UI必须继承此类，此类包含所有UI类共有的逻辑
 */
import { Component, ComponentArgs } from '../filesystem'
export function waitAnimationFrame<T = void>(data?: T): Promise<T> {
    return new Promise(function (resolve, reject) {
        requestAnimationFrame(() => { //等待一帧，确保cpu有空渲染过了
            resolve(data);
        });
    });
}
export let animationFramePending = 0;
export let animationFramePendingInfo: Map<number, { handle: number, stack: string, time: number }> = new Map();

export function requestAnimationFrame(cb: Function): number {
    animationFramePending++;
    let handle = window.requestAnimationFrame((time) => {
        animationFramePendingInfo.delete(handle);
        animationFramePending--;
        cb(time);
    });
    if (animationFramePendingInfo.size > 1000) {//内存保护
        console.error('requestAnimationFrame连续调用大于1000次且都未完成回调.');
        animationFramePendingInfo.clear();
    }
    animationFramePendingInfo.set(handle, { handle: handle, stack: new Error().stack, time: Date.now() });
    return handle;
}
export class IComponent implements Component {

    classList: string[] = [];

    domBase: HTMLElement;

    domParent: HTMLElement;

    id: string;

    /**
     * 通用逻辑：创建domBase,根据classList和id设置domBase
     * @param args 
     * @param tag 
     */
    protected _createDomBase(args: ComponentArgs, tag = "div"): HTMLElement {
        if (args.domBase) {
            this.domBase = args.domBase;
            this.domParent = <HTMLElement>this.domBase.parentNode || null;
        } else {
            this.domBase = document.createElement(tag || "div");
        }
        this.domBase.setAttribute("class", this.classList.join(" "));
        if (args.id !== null && args.id !== undefined) {
            this.domBase.id = args.id;
        }
        this.domBase.szobject = this;
        return this.domBase;
    }

    constructor(args:ComponentArgs) {

    }

    getDomBase(): HTMLElement {
        return this.domBase;
    };

    getDomParent(): HTMLElement {
        return this.domParent;
    };

    setDomParent(domParent?: HTMLElement, beforeNode?: Node): void {
        this.domParent = domParent;
        if (this.domBase === null) {
            /**
             *代表没有初始化完成,不做任何操作 
             */
            return;
        }
        if (domParent === null) {
            /**
             * 代表将此dom移除
             *  */
            this.domBase.remove();
            return;
        }
        /**
         * 如果已经完成挂载，则不用重新挂载
         */
        if (!(this.domBase.parentNode === domParent)) {
            if (beforeNode === null || beforeNode === undefined) {
                /**
                 * 直接append
                 */
                domParent.appendChild(this.domBase)
            } else {
                /**
                 * insertBefore即可
                 */
                domParent.insertBefore(this.domBase, beforeNode)
            }
        }
    };

    setVisible(v: boolean): void {
        this.domBase.style.display = v ? "" : "";
    };

    isVisible(): boolean {
        return this.domBase.style.display === "none" ? false : true;
    };

    setEnabled(v: boolean): void {
        if (v) {
            this.domBase.removeAttribute("disabled");
        } else {
            this.domBase.setAttribute("disabled", "true");
        }
    };

    isEnabled(): boolean {
        if (this.domBase.getAttribute("disabled") === null) {
            return true;
        } else {
            return false;
        }
    };

    setClassName(v: string): void {
        if (this.classList === null) {
            this.classList = [];
        } else {
            if (!this.classList.includes(v)) {
                this.classList.push(v);
                if (this.domBase !== null) {
                    this.domBase.setAttribute("class", this.classList.join(" "));
                }
            }
        }
    };

    removeClassName(v: string): void {
        if (this.classList !== null) {
            if (this.classList.includes(v)) {
                this.classList.splice(this.classList.indexOf(v) - 1, 1);
                this.domBase.setAttribute("class", this.classList.join(" "))
            }
        } else {
            this.classList = [];
        }
    };

    dispose(): void {
        let domBase = this.domBase;
        this.domBase = null;
        domBase.remove();
    };

}